跳到主要内容

Gin 自动绑定参数

// BindAndValid binds and validates data
func bindAndValid(c *gin.Context, form interface{}) error {
err := c.Bind(form)
if err != nil {
return err
}

if err := validate.StructsCtx(c.Request.Context(), form); err != nil {
return err
}

return nil
}

// AutoBindWrap 自动绑定参数
func AutoBindWrap(ctrFunc interface{}) gin.HandlerFunc {
return func(c *gin.Context) {
appG := Gin{C: c}
ctrType := reflect.TypeOf(ctrFunc)
ctrValue := reflect.ValueOf(ctrFunc)
// 1. check
if ctrType.Kind() != reflect.Func {
panic("not support")
}
numIn := ctrType.NumIn()
if numIn != 2 {
panic("not support")
}

// 2. bind value
ctrParams := make([]reflect.Value, numIn)
for i := 0; i < numIn; i++ {
pt := ctrType.In(i)
// handle gin.Context
if pt == reflect.TypeOf(&gin.Context{}) {
ctrParams[i] = reflect.ValueOf(c)
continue
}

// handle params
if pt.Kind() == reflect.Ptr && pt.Elem().Kind() == reflect.Struct {
pv := reflect.New(pt.Elem()).Interface()

err := bindAndValid(c, pv)
if err != nil {
appG.Error(trade_error.NewValidateErr(trade_errcode.InvalidParams, err))
}

ctrParams[i] = reflect.ValueOf(pv)
}
}
// 3. call controller
ctrValue.Call(ctrParams)
}
}

注册服务

package router

import (
"github.com/gin-gonic/gin"
"github.com/seven-yu/gin-auto-bind/app/controller"
)

func RouteV1(e *gin.Engine) {
apiV1 := e.Group("/api/v1")

{
apiV1.GET("hello", controller.Get)
apiV1.POST("hello", controller.Create)

apiV1.GET("auto_bind_hello", AutoBindWrap(controller.AutoBindGet))
apiV1.POST("auto_bind_hello", AutoBindWrap(controller.AutoBindCreate))
}
}

References